package apis

import (
	"encoding/json"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	config2 "github.com/go-admin-team/go-admin-core/config"
	"github.com/go-admin-team/go-admin-core/sdk/api"
	"github.com/go-admin-team/go-admin-core/sdk/config"
	jwt2 "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
	"net/http"
	"strconv"
	"time"
	"tuowei.com/app/api/models"
	"tuowei.com/app/api/service"
	"tuowei.com/app/api/service/dto"
	"tuowei.com/common/actions"
	Beans "tuowei.com/pkg/sing/beans"
	"tuowei.com/pkg/sing/http_utils"
	"tuowei.com/pkg/util"
	"tuowei.com/pkg/xlog"
)

type ApiStudent struct {
	api.Api
	Base
}

func (e ApiStudent) GetUserInfo(c *gin.Context) {
	s := service.ApiStudent{}
	req := dto.SysScoreGeAllReq{}
	scoreSer := service.SysScore{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		MakeService(&scoreSer.Service).
		Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	value, _ := e.Context.Get(jwt2.JwtPayloadKey)
	bytes, _ := json.Marshal(value)
	obj := new(StudentClaims)
	_ = json.Unmarshal(bytes, &obj)
	var student models.SysStudent
	err = s.GerStudentInfo(&student, obj.Student.Id)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	var studyDuration models.SysCourseChapterCompletedRecord

	err = e.Orm.Debug().Model(studyDuration).Where("student_id = ?", obj.Student.Id).First(&studyDuration).Error
	if err != nil {
		studyDuration = models.SysCourseChapterCompletedRecord{}
	}
	if student.LastPayTime != nil && student.LastPayTime.IsZero() {
		student.LastPayTime = nil
	}
	if student.LastPayTime != nil && student.ShenBenTime.IsZero() {
		student.ShenBenTime = nil
	}
	hour, minute, second := resolveTime(studyDuration.TotalStudyDuration)
	student.StudyDuration = strconv.Itoa(hour) + "时" + strconv.Itoa(minute) + "分" + strconv.Itoa(second) + "秒"
	//数据权限检查
	p := actions.GetPermissionFromContext(c)
	var count int64
	list := make([]models.SysScore, 0)
	err, req.BuyerId = e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	err = scoreSer.GetAll(&req, p, &list, &count)

	sum := 0.00
	for _, ll := range list {
		switch ll.Change {
		case 1:
			sum = sum + ll.ScoreChange
		default:
			sum = sum - ll.ScoreChange
		}
	}
	student.Score = sum
	//积分保利2位
	value1, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", sum), 64)
	student.Score = value1
	xlog.Infof("GetUserInfo resp:%+v", student)
	e.OK(&student, "获取成功")
	return
}

func (e ApiStudent) UpdateStudent(c *gin.Context) {
	req := dto.SysStudentUpdateReq{}
	s := service.ApiStudent{}
	err := e.MakeContext(c).
		Bind(&req, binding.JSON).
		MakeOrm().
		MakeService(&s.Service).
		Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	err = s.Update(&req, studentID)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	e.OK(nil, "成功")
	return

}

func (e ApiStudent) DeleteStudent(c *gin.Context) {
	s := service.ApiStudent{}
	err := e.MakeContext(c).
		MakeOrm().
		MakeService(&s.Service).
		Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	err = s.Delete(studentID)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	e.OK(studentID, "成功")
	return

}

func (e ApiStudent) PayBalance(c *gin.Context) {
	req := dto.SysPayBalanceReq{}
	s := service.ApiStudent{}
	err := e.MakeContext(c).
		Bind(&req, binding.JSON).
		MakeOrm().
		MakeService(&s.Service).
		Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	//本接口消费
	req.Change = 2
	req.Title = "购买"
	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	err = s.UpdatePayBalance(&req, studentID, c)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	e.OK(nil, "成功")
	return

}

func (e ApiStudent) MyInviteCode(ctx *gin.Context) {
	s := service.ApiStudent{}
	err := e.MakeContext(ctx).MakeOrm().MakeService(&s.Service).Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	now := time.Now()
	claim := &InviteClaims{
		Id:             studentID,
		StandardClaims: jwt.StandardClaims{},
	}
	claim.StandardClaims.IssuedAt = now.Unix()
	claim.StandardClaims.ExpiresAt = now.Add(time.Duration(config.JwtConfig.Timeout) * time.Second).Unix()
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
	tokenStr, err := token.SignedString([]byte(config.JwtConfig.Secret))
	if err != nil {
		xlog.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	xlog.Info(tokenStr)
	h5Url := config2.Get("H5_URL").String("")
	bytes := util.MakeQrcodeBase64(h5Url+"?token="+tokenStr+"&type=student", 256)
	e.OK(string(bytes), "success")
	return
}

func (e ApiStudent) MyInvite(ctx *gin.Context) {
	s := service.ApiStudent{}
	req := dto.MyInviteStudentListGetPageReq{}
	err := e.MakeContext(ctx).MakeOrm().
		Bind(&req, binding.Form).
		MakeService(&s.Service).Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	list := make([]models.MyInviteStudentList, 0)
	count := int64(0)
	err = s.GetMyInviteList(&req, studentID, &list, &count)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	e.PageOK(list, int(count), req.PageIndex, req.GetPageSize(), "查询成功")
	return
}

func (e ApiStudent) Chronography(c *gin.Context) {
	s := service.ApiStudent{}
	req := dto.ChronographyReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req, binding.JSON).
		MakeService(&s.Service).
		Errors
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}

	err, studentID := e.GetUser(&e.Api)
	if err != nil {
		xlog.Error(err)
		e.Error(401, err, err.Error())
		return
	}
	err = s.Chronography(studentID, &req)
	if err != nil {
		xlog.Error(err)
		e.Error(500, err, err.Error())
		return
	}
	e.OK(nil, "成功")
	return
}

type Base64Req struct {
	File string `json:"file" binding:"required"`
}
type Base64Rsp struct {
	Path string `json:"path"`
}

func (e ApiStudent) UploadBase64(ctx *gin.Context) {
	e.MakeContext(ctx)
	req := Base64Req{}
	if err := ctx.BindJSON(&req); err != nil {
		e.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	rsp, err := util.UploadBase64(ctx, req.File)
	xlog.Error(rsp, err, e)
	if err != nil {
		e.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	e.OK(Base64Rsp{Path: rsp.Path}, "success")
}

func (e ApiStudent) PsnAuthUrl(ctx *gin.Context) {
	req := dto.EsignAutoGenerated{}
	err := e.MakeContext(ctx).Bind(&req, binding.JSON).Errors
	if err != nil {
		e.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	bts, _ := json.Marshal(req)
	r, httpStatus := http_utils.SendCommHttp("/v3/psn-auth-url", string(bts), http.MethodPost)
	if httpStatus != http.StatusOK {
		e.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	rsp := Beans.PsnAuthUrlRsp{}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		e.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	e.OK(rsp.Data, rsp.Message)
}

func (e ApiStudent) CreateByFile(ctx *gin.Context) {
	req := dto.ESignCreateByFileReq{}
	err := e.MakeContext(ctx).Bind(&req, binding.JSON).Errors
	if err != nil {
		e.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	bts, err := json.MarshalIndent(&req, "", " ")
	if err != nil {
		e.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	xlog.Info(string(bts))
	r, httpStatus := http_utils.SendCommHttp("/v3/sign-flow/create-by-file", string(bts), http.MethodPost)
	if httpStatus != http.StatusOK {
		e.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	rsp := Beans.EsignCreateByFileRsp{}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		e.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	e.OK(rsp.Data, rsp.Message)
}

func (e ApiStudent) SignUrl(ctx *gin.Context) {
	req := dto.ESignSignUrlReq{}
	err := e.MakeContext(ctx).Bind(&req, binding.JSON).Errors
	if err != nil {
		e.Error(http.StatusInternalServerError, err, err.Error())
		return
	}
	signFlowId := ctx.Param("signFlowId")
	bts, _ := json.Marshal(&req)
	if err != nil {
		e.Error(http.StatusBadRequest, err, err.Error())
		return
	}
	xlog.Info(string(bts))

	r, httpStatus := http_utils.SendCommHttp(fmt.Sprintf("/v3/sign-flow/%s/sign-url", signFlowId), string(bts), http.MethodPost)
	if httpStatus != http.StatusOK {
		e.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	rsp := Beans.ESignSignUrlRsp{}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		e.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	e.OK(rsp.Data, rsp.Message)
}

//FileDownloadUrl xx
func (e ApiStudent) FileDownloadUrl(ctx *gin.Context) {
	e.MakeContext(ctx)
	signFlowId := ctx.Param("signFlowId")
	url := fmt.Sprintf("/v3/sign-flow/%s/file-download-url", signFlowId)
	r, httpStatus := http_utils.SendCommHttp(url, "", http.MethodGet)
	if httpStatus != http.StatusOK {
		e.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	rsp := Beans.FileDownloadUrlRsp{}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		e.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	e.OK(rsp.Data, rsp.Message)
}

func (e ApiStudent) IdentityInfo(ctx *gin.Context) {
	e.MakeContext(ctx)
	psnAccount := ctx.Param("psnAccount")
	rsp := Beans.IdentityInfoRsp{}
	url := fmt.Sprintf("/v3/persons/identity-info?psnAccount=%s", psnAccount)
	r, httpStatus := http_utils.SendCommHttp(url, "", http.MethodGet)
	if httpStatus != http.StatusOK {
		e.Error(http.StatusInternalServerError, nil, "请求e电签接口错误")
		return
	}
	json.Unmarshal(r, &rsp)
	if rsp.Code != 0 {
		e.Error(http.StatusInternalServerError, nil, rsp.Message)
		return
	}
	e.OK(rsp.Data, rsp.Message)
}
